#pragma once

#include <list>
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
#include <fstream>
#include <assert.h>
#include <stdarg.h>

#include <sal.h>

#include "boost\lambda\casts.hpp"
#include "boost\lambda\lambda.hpp"
//#include "boost\bind\bind.hpp"

namespace ann
{


#   define EK_INIT_VAL 1.0
    // ann status include error and test result
    enum eANN_St
    {
        eann_Normal      = 0x00000000,
        eann_Converged   = 0x00000001,
        eann_Initialized = 0x00000002,
        eann_FOTRDataFile= 0x00001000,
        eann_FETRDataFile= 0x00002000,
        eann_FOINITFile  = 0x00004000,
        eann_FEINITFile  = 0x00008000,
        eann_RBF_StaticInit = 0x00010000,
        eERR_Invalid 
    };

    typedef unsigned int UINT;
    typedef std::vector<UINT> uVec;
    typedef std::vector<double> dVec;

    class node;
    class node_bp;
    typedef std::vector< node* > npVec;
    //typedef std::vector< node_bp* > npVec;

    typedef struct 
    {
        dVec m_inVec;
        dVec m_outVec;
        double m_ek;
    } TRData;
    typedef std::vector< TRData* > trVec;


    typedef const double (*EXCIT_FUNC)(const double, ...);

    inline const double Linear( const double pVal, ... )
    {
        return pVal;
    }

    inline const double Tansig( const double pVal, ... )
    {
        return 1.0 / ( 1.0 + exp( -pVal ));
    }

    inline const double Gaussian( const double pVal, ... )
    {
        va_list vl;
        double pSigma = 0.0;

        va_start(vl, pVal);
        pSigma = va_arg(vl, double);
        va_end(vl);

        return exp( -0.5 * pVal*pVal / (pSigma*pSigma) );
    }

    inline const double Multiquadratic( const double pVal, ... )
    {
        va_list vl;
        double pSigma = 0.0;

        va_start(vl, pVal);
        pSigma = va_arg(vl, double);
        va_end(vl);

        return sqrt( pVal*pVal + pSigma*pSigma );
    }
    
    inline const double GerMultiQuad( const double pVal, ... )
    {
        va_list vl;
        double pSigma = 0.0;
        double pBeta  = 0.0;

        va_start(vl, pVal);
        pSigma = va_arg(vl, double);
        pBeta  = va_arg(vl, double);
        va_end(vl);

        return pow( pVal*pVal+pSigma*pSigma, pBeta );
    }

}
